#pragma once

#include <variant>
#include <type_traits>
#include <stdexcept>
#include "RCS_Debug.h"

/* @brief Option类型
 * @details 使用Template自动生成类似Rust中的Option类型
 * @author 王子恒
 * @date 2025-3-23
 * @code
 * //对于int,int类型生成对应的Result
 * Option<int>
 * //使用：
 * Option<int> divide(int a, int b) {
 *     if (b != 0)
 *         return Some(a / b);;
 *     return None;
 * }
 * void use_option(){
 *     scanf_s("%d%d", &a, &b);
 *     auto ret = divide(a, b);
 *     if (ret.is_none()) {
 *         printf("除数不能为0\n");
 *     } else {
 *         printf("结果为%d\n", *ret);
 *     }
 * }
 * @endcode
 */
struct NoneType {};
extern constexpr NoneType None{};

template <typename T>
class Option {
private:
    std::variant<T, NoneType> data;

public:
    explicit Option(const T& value) : data(value) {}
    explicit Option(T&& value) : data(std::move(value)) {}

    Option(NoneType) : data(NoneType{}) {}

    T& unwrap() {
        if (is_none()) {
						printf("Error: Option is None");
        }
        return std::get<T>(data);
    }

    const T& unwrap() const {
        if (is_none()) {
						printf("Error: Option is None");
        }
        return std::get<T>(data);
    }

    T unwrap_or(T default_value) {
        return is_some() ? unwrap() : default_value;
    }

    T& operator*() { return unwrap(); }
    T* operator->() { return &unwrap(); }

    bool is_some() const { return std::holds_alternative<T>(data); }

    bool is_none() const { return std::holds_alternative<NoneType>(data); }

    template <typename U,
              std::enable_if_t<std::is_convertible_v<U, T>, int> = 0>
    Option(U&& value) : data(std::forward<U>(value)) {}
};

template <typename T>
extern Option<T> Some(T value) {
    return Option<T>(std::move(value));
};



/* @brief Result类型
 * @details 使用Template自动生成类似Rust中的Result类型
 * @author 王子恒
 * @date 2025-3-23
 * @code
 * //对于int类型生成对应的Result
 * Result<int>
 * //使用：
 * auto divide(int a, int b) {
       if (b != 0)
           return Ok<int>(a / b);;
       return Err<int>(-1);//这里里面填的是ErrorCode类型为int
 * }
 * void use_option(){
 *     scanf_s("%d%d", &a, &b);
 *     auto ret = divide(a, b);
 *     if (ret.is_err()) {
 *         printf("除数不能为0\n");
 *         printf("%d\n",ret.unwrap_err().code);
 *     } else {
 *         printf("结果为%d\n", *ret);
 *     }
 * }
 * @endcode
 */
typedef struct {
    int code;
}ErrorCode;
template <typename T, typename E = ErrorCode>
class Result {
private:
    std::variant<T, E> data;

public:
    explicit Result(const T& value) : data(value) {}
    explicit Result(T&& value) : data(std::move(value)) {}
    explicit Result(const E& error) : data(error) {}
    explicit Result(E&& error) : data(std::move(error)) {}

    T& unwrap() {
        if (is_err()) {
						printf("Error: Option is None");
        }
        return std::get<T>(data);
    }

    const T& unwrap() const {
        if (is_err()) {
						printf("Error: Option is None");
        }
        return std::get<T>(data);
    }

    E& unwrap_err() {
        if (is_ok()) {
						printf("Error: Option is None");
        }
        return std::get<E>(data);
    }

    const E& unwrap_err() const {
        if (is_ok()) {
						printf("Error: Option is None");
        }
        return std::get<E>(data);
    }

    bool is_ok() const { return std::holds_alternative<T>(data); }

    bool is_err() const { return std::holds_alternative<E>(data); }

    T& operator*() { return unwrap(); }
    T* operator->() { return &unwrap(); }
};

template <typename T, typename E = ErrorCode>
extern Result<T, E> Ok(T value) {
    return Result<T, E>(std::move(value));
}

template <typename T>
extern Result<T, ErrorCode> Err(int error) {
    return Result<T, ErrorCode>(ErrorCode{std::move(error)});
}

template <typename T,typename E>
extern Result<T, E> Err(E error) {
    return Result<T, E>(std::move(error));
}